#include "vtor_i2c.h"

#ifdef __VTOR_I2C_SLAVE__

void VtorI2cSlave_SclHandler(VtorI2c* i2c)
{
	if(i2c == NULL)
	{
		return ;
	}
	int8_t sclLevel = VtorI2cSlave_ReadScl(i2c);
	int8_t sdaLevel = VtorI2cSlave_ReadSda(i2c);

	if(i2c->oldSclLevel == sclLevel)
	{
		return ;
	}
	i2c->oldSclLevel = sclLevel;
	
	if(sclLevel == 1)
	{
		i2c->sclRisingCnt ++;
	}

	// 8bit下降沿正处理
	// 读模式下，从机在低电平写入sda
	if((i2c->sclRisingCnt  % 9) != 7 && 0 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
		{
			VtorI2cSlave_WriteSda(i2c, i2c->serialRegister >> 7);
			i2c->serialRegister <<= 1;
		}
	}

	// 8bit上升沿正处理
	// 写模式下，从机在上升沿读取sda
	if((i2c->sclRisingCnt % 9) <= 7 && 1 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
		{
			i2c->serialRegister <<= 1;
			i2c->serialRegister |= sdaLevel;
			// 收集到第
		}
	}

	// 8bit再处理
	// 主机写，从机处理接收字节
	if((i2c->sclRisingCnt % 9) == 7 && 1 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
		{
			// 传输完成8个bit，该判断是否回应
			//printf("i2c slave rx 0x%x\r\n", i2c->serialRegister);
			// 做好接收的这个字节的处理，到底是设备地址还是寄存器地址，还是数据
			if(i2c->sclRisingCnt / 9 == 0)
			{
				i2c->devAddr = i2c->serialRegister; // 首次传输设备地址
			}
			else if(i2c->sclRisingCnt / 9 == 1)
			{
				if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
				{
					i2c->regAddr = i2c->serialRegister; // 接下来传输寄存器地址
				}
			}
			else
			{
				if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
				{
					i2c->regData[i2c->regAddr] = i2c->serialRegister; // 数据
					VtorI2cSlave_WriteRegCallback(i2c);
					i2c->regAddr++;
				}
			}
			i2c->serialRegister = 0;
		}
	}

	// ack预处理
	// 调整sda输入输出
	if((i2c->sclRisingCnt % 9) == 7 && 0 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_WRITE)
		{
			if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
			{
				// 设备地址匹配，从机向主机回应
				VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_OUTPUT);
				VtorI2cSlave_WriteSda(i2c, 0);
			}
		}
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
		{
			// 设备地址匹配，从机向主机回应
			VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
		}
	}

	// ack正处理
	// 从机处理主机的nack
	if(i2c->sclRisingCnt % 9 == 8 && 1 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
		{
			// 主机发送nack，说明通信即将结束，从机即将释放sda
			if(sdaLevel == 1)
			{
				i2c->slaveState = VTOR_I2C_SLAVE_STATE_NACK;
			}
		}
	}

	// ack再处理
	// 恢复sda为原本模式，和判断下一个字节将是什么模式
	if(i2c->sclRisingCnt % 9 == 8 && 0 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_NACK)
		{
			VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
		}
		else
		{
			// ack再处理内判断是写模式还是读模式
			if(i2c->devAddr == (i2c->selfDevAddr & 0xfe))
			{
				i2c->slaveState = VTOR_I2C_SLAVE_STATE_WRITE;
					// ack已完成，将sda设置成输入边沿中断
				VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
			}

			// 首次写完地址，判断是不是模式
			if(i2c->devAddr == (i2c->selfDevAddr | 0x01))
			{
				i2c->slaveState = VTOR_I2C_SLAVE_STATE_READ;
				VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_OUTPUT);

			}
		}
	}

	// 8bit预处理
	// 之所以放在最后，是因为 8bit正处理 是从上升沿开始的，
	// 但对sda修改，需要在上升沿之前
	if((i2c->sclRisingCnt  % 9) == 8 && 0 == sclLevel)
	{
		if(i2c->slaveState == VTOR_I2C_SLAVE_STATE_READ)
		{
			i2c->serialRegister = i2c->regData[i2c->regAddr];
			VtorI2cSlave_ReadRegCallback(i2c);
			//printf("i2c slave will tx [0x%x]=0x%x\r\n",
			//	i2c->regAddr, i2c->serialRegister);
			// 如果继续操作，增加当前寄存器坐标
			i2c->regAddr++;

			VtorI2cSlave_WriteSda(i2c, i2c->serialRegister >> 7);
			i2c->serialRegister <<= 1;
		}
	}
}


void VtorI2cSlave_SdaHandler(VtorI2c* i2c)
{
	if(i2c == NULL)
	{
		return ;
	}
	int8_t sclLevel = VtorI2cSlave_ReadScl(i2c);
	int8_t sdaLevel = VtorI2cSlave_ReadSda(i2c);
	// 如果电平没变化，直接返回
	if(i2c->oldSdaLevel == sdaLevel)
	{
		return ;
	}
	i2c->oldSdaLevel = sdaLevel;
	if(sclLevel)
	{
		if(0 == sdaLevel)
		{
			// scl为高，sda下降沿，起始
			i2c->slaveState = VTOR_I2C_SLAVE_STATE_START;
			i2c->slaveState = VTOR_I2C_SLAVE_STATE_WRITE;
			i2c->sclRisingCnt = -1;
		}
		else
		{
			VtorI2cSlave_SetSdaDir(i2c, GPIO_DIR_IT_2EDGE);
			// 只有是访问当前地址，才好触发stop信号
			if((i2c->devAddr & 0xfe) == (i2c->selfDevAddr & 0xfe))
			{
				// scl为高，sda上升沿，结束
				i2c->slaveState = VTOR_I2C_SLAVE_STATE_STOP;
				i2c->devAddr = 0; // 清空总线上的设备地址
				VtorI2cSlave_StopCallback(i2c);
			}
		}
	}
}


uint8_t VtorI2cSlave_WriteBuffer(VtorI2c* i2c, uint8_t* txbuf, uint8_t txLen)
{
	if(i2c == NULL)
	{
		return 0;
	}
	// 从机读取数据后会 将tx len寄存器清零
	// 只有tx len寄存器为0，才能放入新数据
	if(0 == i2c->regData[VTOR_I2C_REG_MISO_BUF_LEN])
	{
		// 复制到内存中，等待i2c主机获取
		memcpy(&i2c->regData[VTOR_I2C_REG_MISO_BUF], txbuf, txLen);
		i2c->regData[VTOR_I2C_REG_MISO_BUF_LEN] = txLen;
		return txLen;
	}
	return 0;
	
}

uint8_t VtorI2cSlave_ReadBuffer(VtorI2c* i2c, uint8_t* rxBuf, uint8_t rxLen)
{
	if(i2c == NULL)
	{
		return 0;
	}
	uint8_t masterTxLen = i2c->regData[VTOR_I2C_REG_MOSI_BUF_LEN];
	// 如果rx len寄存器为0，说明没数据，直接返回
	if(0 == masterTxLen)
	{
		return 0;
	}
	// rxLen使用两者中较小的数字
	if(rxLen > masterTxLen)
	{
		rxLen = masterTxLen;
	}
	// 复制到内存中，等待i2c主机获取
	memcpy(rxBuf, &i2c->regData[VTOR_I2C_REG_MOSI_BUF], rxLen);
	i2c->regData[VTOR_I2C_REG_MOSI_BUF_LEN] = 0;
	rxBuf[rxLen] = '\0';
	return rxLen;
}



#endif // __VTOR_I2C_SLAVE__

